import { merge } from 'lodash';

import type { IndexDto } from '../dto';
import { IndexQueryExp } from '../types';

export function flatQueryDto<T extends IndexDto['query']>(query: T) {
  if (query?.length) {
    const data = query.flatMap((v) => v.exps);

    return data as NonNullable<NonNullable<T>[number]['exps']>;
  }
  return [] as NonNullable<NonNullable<T>[number]['exps']>;
}

export function mergeIndexQuery<T>(object: T, source: IndexDto['query']) {
  return merge(object, source);
}

export function removeIndexQuery(query: IndexDto['query'], props: string[]) {
  return query?.[0]?.exps?.filter((v) => !props.includes(v.prop));
}

export function mergeIndexSort(
  object: IndexDto['sorts'],
  source: IndexDto['sorts'],
) {
  return merge(object, source);
}

export function removeIndexSort() {}

const Operate = {
  number: 'EQ',
  string: 'LIKE',
  rangeDateTime: 'BTW',
  select: 'IN',
} as const;

const createExp = (
  val: any,
  prop: string,
  operateKey: IndexQueryExp,
  i = 0,
): SC.API.Query => ({
  value: val,
  lr: i === 0 ? undefined : 'and',
  prop,
  // @ts-expect-error 类型不匹配
  operate: Operate[operateKey] || operateKey,
});

type OperateType = IndexQueryExp['operate'] | keyof typeof Operate;

/** 查询参数生成格式方法
 *
 * @export
 * @param {string | number | null} val 查询的值
 * @param {string} prop 后端字段
 * @param {Query['operate']} [operateType] 筛选条件 (默认: string)
 * @param {[val, prop, operateType?][]} params - 同 [val, prop, operateType]
 *
 * @example
 * ```js
 * ApiQueryHandler('1', 'active')
 * ApiQueryHandler('2020-08-03', 'createdAt', 'rangeDateTime')
 * ApiQueryHandler([[1, 'active'], ['2020-08-03', 'createdAt', 'rangeDateTime']]);
 * ```
 * @returns {SC.API.IndexQuery}
 */
export function ApiQueryHandler(
  val: string | number | null,
  prop: string,
  operateType?: OperateType,
): SC.API.IndexQuery;
export function ApiQueryHandler(
  params: [string | number | null, string, OperateType?][],
): SC.API.IndexQuery;
export function ApiQueryHandler(
  val: any,
  prop?: any,
  operateType?: any,
): SC.API.IndexQuery {
  const exps: SC.API.IndexQuery[0]['exps'] = [];

  if (Array.isArray(val)) {
    for (let index = 0; index < val.length; index++) {
      const item = val[index];
      exps.push(createExp(item[0], item[1], item[2] || 'string', index));
    }
  } else {
    exps.push(createExp(val, prop, operateType || 'string'));
  }

  return [{ exps }];
}
